package com.tetris;

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;

// 格
class Grid {
    public boolean mUsed;   // 使用则为 true，否则为 false
}

// 带颜色的格
class ColorGrid extends Grid {
    public Color mColor;   // 颜色
}

// 方块
public abstract class Block {
    // 形状
    protected enum Shape {
        ONE,    // 形状1
        TWO,    // 形状2
        THREE,  // 形状3
        FOUR    // 形状4
    }

    protected final Grid[][] mBlocks;   // 方块数据  
    protected final Color mColor;       // 颜色 
    protected Graphics mDrawer;         // 绘图者
    private Component mGameBoard;       // 游戏区域
    protected int mLine;                // 当前所在列(左)
    protected int mRow;                 // 当前所在行(上)
    protected Shape mShape;             // 形状

    /**
     * 构造方法。
     */
    public Block() {
        mBlocks = new Grid[Const.BLOCK_GRID_COUNT_V][Const.BLOCK_GRID_COUNT_H];
        for (int i = 0; i < Const.BLOCK_GRID_COUNT_V; i++) {
            for (int j = 0; j < Const.BLOCK_GRID_COUNT_H; j++) {
                mBlocks[i][j] = new Grid();
            }
        }
        
        final int maxValue = Byte.MAX_VALUE * 2 + 1;
        final Random random = new Random();
        mColor = new Color(random.nextInt(maxValue), random.nextInt(maxValue), random.nextInt(maxValue));
        mLine = 3;
        mRow = -1;
        mShape = Shape.ONE;
    }

    /**
     * 绘制自身。
     */
    protected void draw() {
        for (int i = 0; i < Const.BLOCK_GRID_COUNT_H; i++) {
            for (int j = 0; j < Const.BLOCK_GRID_COUNT_V; j++) {
                if (!mBlocks[i][j].mUsed) {
                    continue;
                }

                final int left = Const.GRID_SIZE * (mLine + j);
                final int top = Const.GRID_SIZE * (mRow + i);
                mDrawer.setColor(mColor);
                mDrawer.fillRect(left, top, Const.GRID_SIZE, Const.GRID_SIZE);
                Block.drawEdge(mDrawer, left, top);
            }
        }

        mGameBoard.repaint();
    }
    
    /*
     * 画矩形的边框，使矩形具有立体效果。
     * @param drawer    绘图者
     * @param left, top 矩形的左上角坐标
     */
    public static void drawEdge(Graphics drawer, int left, int top) {
        final int right = left + Const.GRID_SIZE - 1;
        final int bottom = top + Const.GRID_SIZE - 1;

        drawer.setColor(Const.COLOR_LEFT_TOP_1);
        drawer.drawLine(left, top, right, top);
        drawer.drawLine(left, top, left, bottom);
        
        drawer.setColor(Const.COLOR_LEFT_TOP_2);
        drawer.drawLine(left + 1, top + 1, right - 1, top + 1);
        drawer.drawLine(left + 1, top + 1, left + 1, bottom - 1);
        
        drawer.setColor(Const.COLOR_RIGHT_BOTTOM_1);
        drawer.drawLine(right, top, right, bottom);
        drawer.drawLine(left, bottom, right, bottom);
        
        drawer.setColor(Const.COLOR_RIGHT_BOTTOM_2);
        drawer.drawLine(right - 1, top + 1, right - 1, bottom - 1);
        drawer.drawLine(left + 1, bottom - 1, right - 1, bottom - 1);
    }

    /**
     * 进入游戏区域。
     * @param gameBoard 游戏区域
     * @param drawer    绘图者
     */
    public void enterGameBoard(Component gameBoard, Graphics drawer) {
        mGameBoard = gameBoard;
        mDrawer = drawer;
        this.draw();
    }

    /**
     * 进入预览区域。
     * @param drawer    绘图者
     */
    public void enterPreview(Graphics drawer) {
        final int x = (Const.PREVIEW_WIDTH - Const.GRID_SIZE * 3) / 2;
        final int y = Const.PREVIEW_HEIGHT / 2 - Const.GRID_SIZE * 2;

        // 遍历所有格，跳过无效的，画有效的
        for (int i = 0; i < Const.BLOCK_GRID_COUNT_H; i++) {
            for (int j = 0; j < Const.BLOCK_GRID_COUNT_V; j++) {
                if (!mBlocks[i][j].mUsed) {
                    continue;
                }

                drawer.setColor(mColor);
                drawer.fillRect(x + Const.GRID_SIZE * j, y + Const.GRID_SIZE * i, Const.GRID_SIZE, Const.GRID_SIZE);
                Block.drawEdge(drawer, x + Const.GRID_SIZE * j, y + Const.GRID_SIZE * i);
            }
        }
    }

    /**
     * 擦除。
     */
    protected abstract void erase();

    /**
     * 擦除矩形。
     * @param rect  矩形
     */
    protected void eraseRect(Rectangle rect) {
        mDrawer.setColor(Const.GAME_BOARD_COLOR);
        mDrawer.fillRect(rect.x, rect.y, rect.width, rect.height);
    }
    
    /**
     * 获取底端所在的行数。底端是指方块最下方的有效格。
     * @return 底端所在的行数
     */    
    public abstract int getBottom();

    /**
     * 获取顶端所在的行数。顶端是指方块最上方的有效格。
     * @return 顶端所在的行数
     */
    public abstract int getTop();

    /**
     * 对不能下落的处理。
     */
    protected abstract void handleCannotMoveDown();

    /**
     * 下落。
     * @return 总是 true
     */
    public boolean moveDown() {
        this.erase();
        mRow++;
        this.draw();

        return true;
    }

    /**
     * 左移。
     */
    public void moveLeft() {
        this.erase();
        mLine--;
        this.draw();
    }

    /**
     * 右移。
     */
    public void moveRight() {
        this.erase();
        mLine++;
        this.draw();
    }

    /**
     * 变形。
     */
    public abstract void transform();
}
